package model
{
	import com.adobe.serialization.json.JSON;
	
	import events.ReaderEvent;
	
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.external.ExternalInterface;
	import flash.net.URLRequest;
	import flash.net.URLRequestHeader;
	import flash.system.Capabilities;
	import flash.system.System;
	import flash.utils.Dictionary;
	import flash.utils.escapeMultiByte;
	
	import model.vo.StyleVO;
	
	import service.ReaderService;
	
	import utils.StringEncoders;
	
	import view.ui.PageCont;

	public class ReaderModel extends EventDispatcher
	{
		private static var instance:ReaderModel;
		
		private static var allowInstance:Boolean;
		
		private var _file_url:String;
		
		/**
		 * 是否在内存中缓存住已经加载过的文档。
		 */		
		public var cache_page:Boolean = true;
		
		public var style:StyleVO = new StyleVO();
		
		public var pages:Dictionary = new Dictionary();
		public var pageLoaders:Dictionary = new Dictionary();
		public var pageLoadersInfo:Dictionary = new Dictionary();
		public var pageInloadingProgress:Dictionary = new Dictionary();
		public var loadingTimes:Dictionary = new Dictionary();
		
		private var _total_page_num:int = 0;
		public var current_page:int = 1;
		
		private var _onePageHeight:Number;
		private var _onePageVisibleAmount:int;
		private var _padding_h:Number = 10;
		private var _padding_v:Number = 10;
		private var _onePageWidth:Number;
		private var _org_width:Number = 612;
		/**
		 * 保证之设置以次_org_width 
		 */		
		private var _haveSetOrgWidth:Boolean = false;
		private var _org_height:Number = 792;
		private var _targetWidth:Number = 0;
		private var _targetHeight:Number = 0;
		private var _totalHeight:Number = 0;
		private var _sourceScale:Number;
		private var _viewScale:Number = 1;
		
		private var _viewMode:int = 0;
		private var _scaleID:int = 0;
		private var _thumbCountsID:int = 0;
		private var _totalLine:int;
		private var _thumbWidth:Number;
		private var _thumbHeight:Number;
		private var _onePageVisibleAmountThumb:int;
		private var _onePageVisibleThumblines:int;
		
		private var _totalHeightThumb:Number;
		
		private var _sourceScaleThumb:Number;
		
		public var pre_totalHeight:Number;
		
		public var pre_onePageHeight:Number;
		
		public var scroll_speed:int = 30;
		
		public var block:Boolean = false;
		
		private var _s:ReaderService = ReaderService.getInstance();
		
		private var _file_url_validate:Boolean = false;
		
		public var isLinkMode:Boolean = false;
		
		public function ReaderModel()
		{
			if(!allowInstance)
			{
				throw(new Error("use ReaderModel.getInstance()"));
			}else{
				if(Capabilities.version.indexOf("MAC") >= 0) scroll_speed = 3;
				else scroll_speed = 20;
			}
		}
		
		public static function getInstance():ReaderModel
		{
			if(instance == null)
			{
				allowInstance = true;
				instance = new ReaderModel();
				allowInstance = false;
			}
			return instance;
		}
		
		public function destroy():void
		{
			_file_url_validate = false;
			_total_page_num = 0;
			current_page = 1;		
			_org_width = 612;
			
			_haveSetOrgWidth = false;
			_org_height = 792;
			_targetWidth = 0;
			_targetHeight = 0;
			_totalHeight = 0;
			_sourceScale;
			_viewScale = 1;
			
			_viewMode = 0;
			_scaleID = 0;
			_thumbCountsID = 0;
			
			pages = new Dictionary();
			pageLoaders = new Dictionary();
			pageInloadingProgress = new Dictionary();
			pageLoadersInfo = new Dictionary();
		}
		
		public function getPage(pid:int):DisplayObject
		{
			if(pages[pid] == null){
				pages[pid] = new PageCont(pid, org_width, org_height);
//				loadPage(pid);	
			}
			return pages[pid];
		}
		
		public function jumpToPage(pid:int):void
		{
			if(pid < 1 || pid > total_page_num) return;
			dispatchEvent(new ReaderEvent(ReaderEvent.JUMP_PAGE, {pid: pid}));
		}
		
		public function loadPage(pid:int):void
		{
			if(!_file_url_validate) return;	
			if(pageInloadingProgress[pid] != null) return;
			if(pages[pid] != null)
			{
				if(PageCont(pages[pid]).target != null)
				{
					dispatchEvent(new ReaderEvent(ReaderEvent.PAGE_LOADED, {pid: pid}));
					return;
				}				
			}
			
//			trace(">>> try to load::::" + pid);
			var ld:Loader = new Loader();
			var req:URLRequest;
			if(isLinkMode) req = new URLRequest(_file_url + "&p=" + pid);
			else req = new URLRequest(encodeURI(_file_url + "&p=" + pid));
			
			ld.load(req);
//			ld.load(new URLRequest("pages/p" + pid + ".pdf")); //本地测试版本代码
			
			ld.contentLoaderInfo.addEventListener(Event.COMPLETE, onPageLoaded);
			ld.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onPageIOError);
			
			pageLoaders[ld.contentLoaderInfo] = pid;	
			pageInloadingProgress[pid] = ld;
			if(loadingTimes[pid] == null) loadingTimes[pid] = 0;
			else loadingTimes[pid] += 1;
		}
		
		protected function onPageIOError(e:IOErrorEvent):void
		{
			var pid:int = pageLoaders[e.target];
			var t:int = loadingTimes[pid];
			if(t > style.io_check - 1){
//				trace(">>>>>>>加载不到::" + pid);
				if(ReaderService.JS_API == ""){
					if(ExternalInterface.available) ExternalInterface.call("alert", "IOError: 无法加载第" + pid);
				}else{
					var obj:Object = {};
					obj.code = 1;
					obj.message = "IOError: 无法加载第" + pid;
					if(ExternalInterface.available) ExternalInterface.call(ReaderService.JS_API, JSON.encode(obj));
				}		
				PageCont(pages[pid]).failedToLoadFile();		
			}else{
				delete pageLoaders[e.target];
				delete pageInloadingProgress[pid];
				loadPage(pid);
			}			
		}
		
		protected function onPageLoaded(event:Event):void
		{
			var ldinfo:LoaderInfo = event.target as LoaderInfo;
			var ld:Loader = ldinfo.loader;
			
			this.org_height = ld.content.height;
			this.org_width = ld.content.width;
			
			var pid:int = pageLoaders[ld.contentLoaderInfo];
			
			PageCont(pages[pid]).target = ld.content;
			if(_viewMode == 0) PageCont(pages[pid]).scaleTo(_sourceScale, true);
			else PageCont(pages[pid]).scaleTo(_sourceScaleThumb, true);
			
			dispatchEvent(new ReaderEvent(ReaderEvent.PAGE_LOADED, {pid: pid}));
			
			delete pageLoaders[ld.contentLoaderInfo];
			delete pageInloadingProgress[pid];
		}
		
		public function refresh():void
		{
			dispatchEvent(new ReaderEvent(ReaderEvent.PAGE_REFRESH));
		}
		
		public function scaleDown():void
		{
			if(viewMode == 0)
			{
				if(_scaleID - 1 < 0) return;
				_scaleID -= 1;
				viewScale = style.scales[_scaleID];
			}else{				
				if(_thumbCountsID + 1 > style.thumbCounts.length - 1) return;
				_thumbCountsID += 1;
				this.targetWidth = _targetWidth;
				this.targetHeight = _targetHeight;
				dispatchEvent(new ReaderEvent(ReaderEvent.VIEW_THUMB_COUNTS_CHANGED));		
			}
			dispatchEvent(new ReaderEvent(ReaderEvent.REFRESH_BUTTON_STATUS));
		}
		
		public function scaleUp():void
		{
			if(viewMode == 0)
			{
				if(_scaleID + 1 > style.scales.length - 1) return;
				_scaleID += 1;
				viewScale = style.scales[_scaleID];
			}else{
				
				if(_thumbCountsID - 1 < 0) return;
				_thumbCountsID -= 1;
				this.targetWidth = _targetWidth;
				this.targetHeight = _targetHeight;
				dispatchEvent(new ReaderEvent(ReaderEvent.VIEW_THUMB_COUNTS_CHANGED));
			}
			dispatchEvent(new ReaderEvent(ReaderEvent.REFRESH_BUTTON_STATUS));
		}

		/**
		 * 阅读模式,0：普通，1：所略图
		 */
		public function get viewMode():int { return _viewMode; }
		public function set viewMode(value:int):void
		{
			if(value == _viewMode) return;
			_viewMode = value;
			
			_viewScale = 1;
			_scaleID = style.scales.indexOf(1);
			
			if(_viewMode == 0)
			{
				_totalHeight = (_onePageHeight + _padding_v) * total_page_num - _padding_v;
			}else{
				var onelineCount:int = style.thumbCounts[_thumbCountsID];
				var totalLine:int = Math.ceil(total_page_num / onelineCount);
				_totalHeight = _thumbHeight * totalLine + _padding_v * (totalLine - 1);
			}
			dispatchEvent(new ReaderEvent(ReaderEvent.VIEW_MODE_CHANGED));
			dispatchEvent(new ReaderEvent(ReaderEvent.REFRESH_BUTTON_STATUS));
		}

		public function get onePageHeight():Number { return _onePageHeight; }
		public function set onePageHeight(value:Number):void
		{
			_onePageHeight = value;
		}
		
		public function get onePageVisibleAmount():int { return _onePageVisibleAmount; }
		public function set onePageVisibleAmount(value:int):void
		{
			_onePageVisibleAmount = value;
		}

		public function get onePageWidth():Number { return _onePageWidth; }
		public function set onePageWidth(value:Number):void
		{
			_onePageWidth = value;
		}

		public function get org_width():Number { return _org_width; }
		public function set org_width(value:Number):void
		{
			if(value == _org_width && _haveSetOrgWidth) return;
			_haveSetOrgWidth = true;
			_org_width = value;
			this.targetHeight = targetHeight;
			this.targetWidth = targetWidth;
			refresh();
		}

		public function get org_height():Number { return _org_height; }
		public function set org_height(value:Number):void
		{
			if(value == _org_height) return;
			_org_height = value;
		}

		public function get targetWidth():Number { return _targetWidth; }
		public function set targetWidth(value:Number):void
		{
//			if(_targetWidth == 0)
			{
				_sourceScale = value / _org_width;
				_onePageWidth = _org_width * _sourceScale;
				_onePageHeight = _org_height * _sourceScale;
				
				var onelineCount:int = style.thumbCounts[_thumbCountsID];
				var totalLine:int = Math.ceil(total_page_num / onelineCount);
				_thumbWidth = (value - (onelineCount -1) * _padding_h) / onelineCount;
				_sourceScaleThumb = _thumbWidth / _org_width;
//				trace(_sourceScaleThumb);
				_thumbHeight = _org_height * _sourceScaleThumb;	
//				_totalHeightThumb = _thumbHeight * onelineCount + _padding_v * (onelineCount - 1); 
			}
			_targetWidth = value;		
		}
		
		public function get targetHeight():Number { return _targetHeight; }
		public function set targetHeight(value:Number):void
		{
//			if(_targetHeight == 0)
			{
				_onePageVisibleAmount = Math.ceil(value / _onePageHeight);
				_totalHeight = (_onePageHeight + _padding_v) * total_page_num - _padding_v;
				var onelineCount:int = style.thumbCounts[_thumbCountsID];
				_onePageVisibleAmountThumb = (Math.ceil(value / (_thumbHeight + _padding_v))  + 1)* onelineCount;
				_onePageVisibleThumblines = Math.ceil(value / (_thumbHeight + _padding_v)) + 1;
			}
			
			if(_viewMode == 0)
			{
				_totalHeight = (_onePageHeight + _padding_v) * total_page_num - _padding_v;
			}else{
				var totalLine:int = Math.ceil(total_page_num / onelineCount);
				_totalHeight = _thumbHeight * totalLine + _padding_v * (totalLine - 1);
			}
			
			
			_targetHeight = value;
			
			if(style.scales[0] != 1)
			{
				style.scales.shift();
				_scaleID -= 1;
			}
			
			var per1:Number = _onePageWidth / _onePageHeight;
			var per2:Number = _targetWidth / _targetHeight;
					
			if(per1 < per2)
			{
				var extraScale:Number = _targetHeight / _onePageHeight;
				if(style.scales[0] == 1)
				{
					style.scales.unshift(extraScale);
					_scaleID += 1;
				}				
			}
			viewScale = style.scales[_scaleID];
			dispatchEvent(new ReaderEvent(ReaderEvent.REFRESH_BUTTON_STATUS));
		}

		public function get sourceScale():Number { return _sourceScale; }
		public function set sourceScale(value:Number):void
		{
			_sourceScale = value;
		}

		public function get padding_h():Number { return _padding_h; }
		public function set padding_h(value:Number):void
		{
			_padding_h = value;
		}

		public function get padding_v():Number { return _padding_v; }
		public function set padding_v(value:Number):void
		{
			_padding_v = value;
		}

		public function get totalHeight():Number 
		{ 
			return _viewMode == 0 ? _totalHeight * _viewScale : _totalHeight; 
		}
		public function set totalHeight(value:Number):void
		{
			_totalHeight = value;
		}

		public function get viewScale():Number { return _viewScale; }
		public function set viewScale(value:Number):void
		{
			if(value == _viewScale) return;
			_viewScale = value;
			dispatchEvent(new ReaderEvent(ReaderEvent.VIEW_SCALE_CHANGED));
		}

		/**
		 * 和stylevo的thumbCounts 
		 */
		public function get thumbCountsID():int { return _thumbCountsID; }
		/**
		 * @private
		 */
		public function set thumbCountsID(value:int):void
		{
			_thumbCountsID = value;
		}

		public function get onePageVisibleAmountThumb():int { return _onePageVisibleAmountThumb; }

		public function get thumbWidth():Number { return _thumbWidth; }
		
		public function get thumbHeight():Number { return _thumbHeight; }

		public function get sourceScaleThumb():Number { return _sourceScaleThumb; }

		public function get onePageVisibleThumblines():int { return _onePageVisibleThumblines; }

		public function get scaleID():int { return _scaleID; }

		public function get file_url():String { return _file_url; }
		public function set file_url(value:String):void
		{
			_file_url = value;
		}

		public function get total_page_num():int { return _total_page_num; } 
		public function set total_page_num(value:int):void
		{
			_total_page_num = value;
			_file_url_validate = true;
			refresh();
		}

		
	}
	
}